;;;
;;; Cuty: Data Conversion utilities
;;; 
BITS 64
;;; 
;;;  LICENSE AGREEMENT:
;;; 
;;;  You agree that we don't agree to anything.
;;; 
;;; 
;;;  DISCLAIMER OF WARRANTIES:
;;; 
;;;  This software is provided to you "AS IS," and the authors and
;;;  contributors disclaim any warranty or liability obligations to you
;;;  of any kind, implied or express, including but not limited to the
;;;  warranties of merchantability, fitness for a particular purpose,
;;;  and non-infringement.
;;; 
section .data align=16
nxp1 dw 0,0,0,0,0,0,0,0 ; packed w
nyp1 dw 0,0,0,0,0,0,0,0	; packed w
pjxs dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
pjys dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
pjzs dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
     dq 0,0,0,0,0,0,0,0
pws dq 0,0,0,0,0,0,0,0
    dq 0,0,0,0,0,0,0,0
    dq 0,0,0,0,0,0,0,0
    dq 0,0,0,0,0,0,0,0
;;; 
section .text align=16
%assign rc   0x04
;;; 
global initenvc_
global initenvd_
global cpptra_
global cpptrax_
global cpptray_
global cpptraxy_
global cpptrb_
global cpptrbx_
global cpptrby_
global cpptrbxy_
global memcp_
;;;
;;; subroutine initenvc(nx,ny,nz)
;;;
%macro st8w 1
	push ax
	push ax
	push ax
	push ax
	push ax
	push ax
	push ax
	push ax
	movdqa xmm0, [rbp-16]
	movdqa [%1], xmm0
	add rsp, 16
%endmacro
;;; 
initenvc_:
	push rbp
	mov rbp, rsp
	;;
	mov rax, rdi
	and rax, 0xFFFF
	inc rax
	st8w nxp1
	;;
	mov rax, rsi
	and rax, 0xFFFF
	inc rax
	st8w nyp1
.exit:
	pop rbp
	ret
;;; 
%macro stptr 0
	mov [rdi], rsi
%rep 31
	add rsi, rax
	add rdi, 8
	mov [rdi], rsi
%endrep
%endmacro	
;;; 
initenvd_:
	push rbp
	mov rbp, rsp
	;;
	mov rax, rdi		; nbufj
	shl rax, 1		; nbufj*2
	mov rdi, pjxs		;
	stptr
	mov rdi, pjys		;
	mov rsi, rdx		; ptr jys(1,1)
	stptr
	mov rdi, pjzs		;
	mov rsi, rcx		;
	stptr
	mov rax, r9		; nbufw
	mov rdi, pws		;
	mov rsi, r8		;
	shl rax, 2		; nbufw*4
	stptr
.exit:
	pop rbp
	ret
;;; 
;;; subroutine cpptra(n,pbuf,px,py,pz,pw)
;;;
%assign px  0x18
%assign py  0x20
%assign pz  0x28
%assign pw  0x30
%assign r   0x38
%assign n   0x40
%assign pb  0x48
%assign m   0x50
%assign s   0x58
%assign buf 0x70
;;; n must be greater than 8 !!!
%macro  cpptr 3			; ref-x, ref-y, xch-xy
	;; 
	push rbp
	mov rbp, rsp
	push rbx
	;; 
	mov rax, rdx		; i
	dec rax
	;; 
	mov rdx, pjxs		;
	mov rcx, pjys		;
	mov r8, pjzs		;
	mov r9, pws		;
	;; 
	lea rdx, [rdx+rax*8]
	lea rcx, [rcx+rax*8]
	lea r8, [r8+rax*8]
	lea r9, [r9+rax*8]
	;;
	mov rdx, [rdx]
	mov rcx, [rcx]
	mov r8, [r8]
	mov r9, [r9]
	;; 
	mov rax, rdi		; 1st n
	;;
 	mov [rbp-px], rdx
 	mov [rbp-py], rcx
 	mov [rbp-pz], r8
 	mov [rbp-pw], r9
	;;
	;; rsi = x in pbuf
%if %3 == 0
;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	mov [rbp-pb], rsi	;
	lea rbx, [rsi+rax*2]	; y in pbuf
	lea r8,  [rbx+rax*2]	; z in pbuf
	lea r9,  [r8+rax*2]	; w in pbuf
%else
	mov rbx, rsi
	mov [rbp-pb], rbx	;
	lea rsi, [rbx+rax*2]	;
	lea r8, [rsi+rax*2]	;
	lea r9, [r8+rax*2]	;
%endif

	;; 
%if %1 != 0 || %2 != 0
	mov [rbp-m], rax	; save n
%endif
	;; 
	mov rdx, rax		; rcx = n
	shr rdx, 2		;
	mov rcx, rdx		; rcx = n/4
	shl rdx, 2		; rdx = 4(n/4)
	sub rax, rdx		; rax = r = mod(n,4)
	mov [rbp-r], rax	; save r
	mov [rbp-n], rcx	; save n/4
	;;
%if %1 != 0 || %2 != 0
	mov rax, [rbp-m]	;
	mov rdx, rax		; rcx = n
	shr rdx, 3		;
	mov rcx, rdx		; rcx = n/8
	shl rdx, 3		; rdx = 8(n/8)
	sub rax, rdx		; rax = r = mod(n,8)
	mov [rbp-s], rax	; save r
	mov [rbp-m], rcx	; save n/8
%endif
	;;
	cld			;
	;; 
	mov rdi, [rbp-px]	;
%if %1 == 0 
	mov rcx, [rbp-n]	;
	rep movsq		;
	mov rcx, [rbp-r]	;
	rep movsw		;
%else
	movdqa xmm2, [nxp1]	;
 	mov rcx, [rbp-m]	;
%%.dox:
  	movdqa xmm0, xmm2	;
;;;   	movdqu xmm1, [rsi]
movq xmm1, [rsi]
movq xmm3, [rsi+8]
unpcklpd xmm1, xmm3
;;; 
 	psubw xmm0, xmm1	;
  	movdqa [rdi], xmm0	;
 	add rsi, 16		;
	add rdi, 16		;
 	dec rcx			;
 	jg %%.dox		;
	;; 
 	mov rcx, [rbp-s]
	or rcx, rcx		;
	jz .xdone		;
	;; 
;;;   	movdqu xmm1, [rsi]
movq xmm1, [rsi]
movq xmm3, [rsi+8]
unpcklpd xmm1, xmm3
;;; 
	psubw xmm2, xmm1	;
 	movdqa [rbp-buf], xmm2	;
	lea rsi, [rbp-buf]	;
  	rep movsw		;
%endif
.xdone:
	;;
	mov rdi, [rbp-py]	;
	mov rsi, rbx		;
%if %2 == 0
	mov rcx, [rbp-n]	;
	rep movsq		;
	mov rcx, [rbp-r]	;
	rep movsw		;
%else
	movdqa xmm2, [nyp1]	;
	mov rcx, [rbp-m]	;
%%.doy:
	movdqa xmm0, xmm2	;
;;; 	movdqu xmm1, [rsi]	;
movq xmm1, [rsi]
movq xmm3, [rsi+8]
unpcklpd xmm1, xmm3
;;; 
	psubw xmm0, xmm1	;
	movdqa [rdi], xmm0	;
	add rsi, 16		;
	add rdi, 16		;
	dec rcx			;
	jg %%.doy		;
	;; 
	mov rcx, [rbp-s]	;
	or rcx, rcx		;
	jz .ydone		;
	;;
;;; 	movdqu xmm1, [rsi]	;
movq xmm1, [rsi]
movq xmm3, [rsi+8]
unpcklpd xmm1, xmm3
;;; 
	psubw xmm2, xmm1	;
	movdqa [rbp-buf], xmm2	;
	lea rsi, [rbp-buf]	;
	rep movsw		;
%endif
.ydone:
	;;
	mov rdi, [rbp-pz]	;
	mov rcx, [rbp-n]	;
	mov rsi, r8		;
	rep movsq		;
	mov rcx, [rbp-r]	;
	rep movsw		;
	;;
	mov rdi, [rbp-pw]	;
	mov rcx, [rbp-n]	;
	mov rsi, r9		;
	shl rcx, 1		;
	rep movsq		;
	mov rcx, [rbp-r]	;
	rep movsd
	;;	
.exit:
	;;
	pop rbx
	pop rbp
	ret
%endmacro
;;;
cpptra_:   cpptr 0, 0, 0
cpptrax_:  cpptr 1, 0, 0
cpptray_:  cpptr 0, 1, 0
cpptraxy_: cpptr 1, 1, 0
cpptrb_:   cpptr 0, 0, 1
cpptrbx_:  cpptr 1, 0, 1
cpptrby_:  cpptr 0, 1, 1
cpptrbxy_: cpptr 1, 1, 1
;;; 
memcp_:
	;; 
	push rbp
	mov rbp, rsp
	;;
	mov rcx, rdx		; n
	cld
	rep movsb
	;;
	pop rbp
	ret
